package com.letoken.platform.app.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.letoken.platform.app.service.AppUserIssueService;
import com.letoken.platform.app.service.AppUserTeamPathService;
import com.letoken.platform.app.service.AppUserTeamService;
import com.letoken.platform.pub.constant.ConstantsValue;
import com.letoken.platform.pub.enums.LetokenApiResponseEnum;
import com.letoken.platform.pub.exception.ApiServiceException;
import com.letoken.platform.pub.req.PageData;
import com.letoken.platform.pub.req.QueryReqBase;
import com.letoken.platform.pub.util.LocalDateTool;
import com.letoken.platform.repo.app.dao.AppUserTeamMapper;
import com.letoken.platform.repo.app.dao.AppUserTeamPathMapper;
import com.letoken.platform.repo.app.manager.AppUserManager;
import com.letoken.platform.repo.app.manager.AppUserTeamManager;
import com.letoken.platform.repo.app.manager.AppUserTeamMemberManager;
import com.letoken.platform.repo.app.manager.AppUserTeamPathManager;
import com.letoken.platform.repo.app.po.*;
import com.letoken.platform.repo.app.redis.AppLoginTokenRedis;
import com.letoken.platform.repo.app.req.team.AppBindInvitationCodeReq;
import com.letoken.platform.repo.app.req.team.ConsumerValueHistoryReq;
import com.letoken.platform.repo.app.res.team.*;
import com.letoken.platform.repo.helper.CalculateConsumerValue;
import com.letoken.platform.repo.utlis.PageDataUtil;
import com.letoken.platform.repo.utlis.WebUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import static com.letoken.platform.pub.constant.RedisKeyConstant.APP_CONSUMER_DATE_MARK;

/**
 * @author letokenlabs
 * @date 2022/11/21$
 */
@Service
@Log4j2
public class AppUserTeamServiceImpl extends ServiceImpl<AppUserTeamMapper, AppUserTeam> implements AppUserTeamService {


    @Autowired
    private AppUserManager appUserManager;

    @Resource
    private AppUserTeamMapper teamMapper;

    @Resource
    private AppUserTeamManager appUserTeamManager;

    @Resource
    private AppUserTeamPathMapper pathMapper;

    @Resource
    private AppUserTeamPathManager appUserTeamPathManager;

    @Resource
    private AppUserTeamPathService appUserTeamPathService;

    @Resource
    private AppUserTeamMemberManager appUserTeamMemberManager;

    @Resource
    private AppUserTeamMapper appUserTeamMapper;
    @Resource
    private AppUserIssueService appUserIssueService;

    @Resource
    private AppUserTeamPathMapper appUserTeamPathMapper;

    @Autowired
    private AppUserTeamService appUserTeamService;
    @Autowired
    CalculateConsumerValue calculateConsumerValue;

    /**
     * 绑定邀请码
     *
     * @param req
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public AppBindInvitationCodeRes bindInvitationCode(AppBindInvitationCodeReq req) {
        AppUser user = appUserManager.queryMe();
        if (user.getInviterId() == null) {
            user.setInviterId(0);
        }
        if (!user.getInviterId().equals(0)) {
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_APP_USER_005);
        }

        AppUser invitationUser = appUserManager.queryInvitationUser(req.getInvitationCode());
        if (ObjectUtil.isNull(invitationUser)) {
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_APP_USER_007);
        }
        if (invitationUser.getId().equals(user.getId())) {
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_APP_USER_008);
        }
        //邀请人不能绑定团队下级邀请码
        AppUserTeamPath invitationUserTeamPath = pathMapper.selectById(invitationUser.getId());
        if (ObjectUtil.isNotNull(invitationUserTeamPath)) {
            if (StringUtils.contains(invitationUserTeamPath.getInvitePath(), user.getId().toString())) {
                throw new ApiServiceException(LetokenApiResponseEnum.ERROR_APP_USER_014);
            }
        }

        LocalDateTime now = LocalDateTime.now();
        //查询被推荐人团队信息
        AppUserTeam appUserTeam = this.getById(user.getId());
        appUserTeam.setBandTime(now);
        appUserTeam.updateById();
        //查询推荐人团队信息 和 团队业绩 并修改
        AppUserTeam invitationTeam = this.getById(invitationUser.getId());
        AppUserTeam invitationTeam2 = new AppUserTeam();
        invitationTeam2.setUserId(invitationTeam.getUserId());
        invitationTeam2.setTeamMember(invitationTeam.getTeamMember() + appUserTeam.getTeamMember() + 1);

        invitationTeam2.setUpdateTime(now);
        if(appUserTeam.getTeamSumValue() > 0 || appUserTeam.getUserAchievement() >0){
            invitationTeam2.setTeamSumValue(invitationTeam.getTeamSumValue()+appUserTeam.getTeamSumValue()+appUserTeam.getUserAchievement());
        }

        if(appUserTeam.getTeamMallAchievement().compareTo(BigDecimal.ZERO) >0  || appUserTeam.getMallCchievement().compareTo(BigDecimal.ZERO) >0){
            invitationTeam2.setTeamMallAchievement(invitationTeam.getTeamMallAchievement().add(appUserTeam.getTeamMallAchievement().add(appUserTeam.getMallCchievement())));
        }

        if(appUserTeam.getTeamfundAchievement().compareTo(BigDecimal.ZERO) >0  || appUserTeam.getFundCchievement().compareTo(BigDecimal.ZERO) >0){
            invitationTeam2.setTeamfundAchievement(invitationTeam.getTeamfundAchievement().add(appUserTeam.getTeamfundAchievement().add(appUserTeam.getFundCchievement())));
        }
        this.updateById(invitationTeam2);

        //修改被推荐人上级用户id
        AppUserTeam appUserTeam2 = new AppUserTeam();
        appUserTeam2.setUserId(appUserTeam.getUserId());
        appUserTeam2.setUpdateTime(now);
        appUserTeam2.setInviterId(invitationTeam.getUserId());
        this.updateById(appUserTeam2);

        //修改被推荐人path 先查询推荐人的path
        AppUserTeamPath appUserTeamPath4 = pathMapper.selectById(invitationTeam.getUserId());
        AppUserTeamPath appUserTeamPath5 = new AppUserTeamPath();
        if (appUserTeamPath4.getInvitePath() != null && !"".equals(appUserTeamPath4.getInvitePath())) {
            appUserTeamPath5.setInvitePath(appUserTeamPath4.getUserId() + "," + appUserTeamPath4.getInvitePath());
        } else {
            appUserTeamPath5.setInvitePath(appUserTeamPath4.getUserId().toString());
        }
        appUserTeamPath5.setUserId(appUserTeam.getUserId());
        pathMapper.updateById(appUserTeamPath5);


        //查询推荐人上级 并 修改团队成员人数
        if (invitationTeam.getInviterId() != null && !invitationTeam.getInviterId().equals(0)) {
            AppUserTeamPath appUserTeamPath = pathMapper.selectById(invitationUser.getId());
            String[] path = appUserTeamPath.getInvitePath().split(",");
            //计算团队人数  所有上级的团队人数都要加1
            boolean addInviteTeamMemberFlag = appUserTeamManager.addInviteTeamMember(path, appUserTeam.getTeamMember());
            if (!addInviteTeamMemberFlag) {
                throw new ApiServiceException(LetokenApiResponseEnum.ERROR_APP_USER_015);
//            for (String id : path) {
//                AppUserTeam invitation = this.getById(id);
//                AppUserTeam appUserTeam3 = new AppUserTeam();
//                appUserTeam3.setUserId(Integer.parseInt(id));
//                appUserTeam3.setUpdateTime(now);
//                appUserTeam3.setTeamMember(invitation.getTeamMember() + appUserTeam.getTeamMember() + 1);
//                this.updateById(appUserTeam3);
//            }
            }
        }

        //修改被推荐人 所有团队用户path
//        List<AppUserTeamPath> pathList = pathMapper.getPathList(appUserTeam.getUserId());
//        if (pathList != null && pathList.size() > 0) {
//            for (AppUserTeamPath appUserTeamPath : pathList) {
//                appUserTeamPath.setInvitePath(appUserTeamPath.getInvitePath() + "," + appUserTeamPath5.getInvitePath());
//                pathMapper.updateById(appUserTeamPath);
//            }
//        }
        // 拿到所有自己的下级
        List<Integer> pathIdList = pathMapper.queryTeamPathUserIdByInviteId(appUserTeam.getUserId());
        //修改自己所有下级的path路径，内容是加上我上级的所有上级  因为我的上级也有也可能有很多上级
        if (CollUtil.isNotEmpty(pathIdList)) {
            appUserTeamPathManager.updateTeamPathByInvite(pathIdList, appUserTeamPath5.getInvitePath());
        }

        user.setInviterId(invitationUser.getId());
        user.updateById();
        //修改推荐人等级  和  生态建设值
       // appUserIssueService.upgrade(user.getId(),null,invitationUser.getId(),1);
      //  appUserIssueService.upgradeUPdate(user.getId(), BigDecimal.ZERO,1);
        //修改推荐人上级团队业绩
        if(appUserTeam.getTeamSumValue() > 0 || appUserTeam.getUserAchievement() >0){
            appUserIssueService.addTeamValue(invitationUser.getId(),new BigDecimal(appUserTeam.getTeamSumValue()+appUserTeam.getUserAchievement()),1);

        }
        if(appUserTeam.getMallCchievement().compareTo(BigDecimal.ZERO) > 0  || appUserTeam.getTeamMallAchievement().compareTo(BigDecimal.ZERO) > 0){
           addMallTeamValue(invitationUser.getId(),appUserTeam.getTeamMallAchievement().add(appUserTeam.getMallCchievement()));
        }
        if(appUserTeam.getFundCchievement().compareTo(BigDecimal.ZERO) > 0  || appUserTeam.getTeamfundAchievement().compareTo(BigDecimal.ZERO) > 0){
           // addMallTeamValue(invitationUser.getId(),appUserTeam.getTeamMallAchievement().add(appUserTeam.getMallCchievement()));
            addFundTeamValue(invitationUser.getId(),appUserTeam.getTeamfundAchievement().add(appUserTeam.getFundCchievement()));
        }

        //更新用户缓存
        AppLoginTokenRedis.me().put(WebUtils.getToken(), user);
        AppBindInvitationCodeRes res = new AppBindInvitationCodeRes();
        res.setInvitationCode(req.getInvitationCode());
        res.setUserName(invitationUser.getUserName());
        res.setUserId(invitationUser.getId());
        return res;
    }


    /**
     * 查询团队基本信息
     *
     * @return
     */
    @Override
    public QueryTeamRes queryTeamInfo() {
        Integer userId = WebUtils.getUserId();
        QueryTeamRes res = teamMapper.queryTeamInfo(userId);
        return res;
    }

    /**
     * 查询团队成员
     *
     * @return
     */
    @Override
    public PageData<QueryTeamMemberRes> queryTeamMembers(QueryReqBase req) {
        Integer userId = WebUtils.getUserId();
        Page<QueryTeamMemberRes> page = new Page<>(req.getPageReq().getPage(), req.getPageReq().getSize());
        Page<QueryTeamMemberRes> teamPage = teamMapper.queryTeamMembers(page, userId);
        return PageDataUtil.getPageData(teamPage);
    }

    /**
     * 生态等级建设-配置信息
     *
     * @return
     */
    @Override
    public List<QueryTeamLevelInfoRes> queryTeamLevelInfo() {
        return teamMapper.queryTeamLevelInfo();
    }

    /**
     * 查询用户生态建设值
     *
     * @return
     */
    @Override
    public QueryTeamLevelRes queryTeamLevel() {
        Integer userId = WebUtils.getUserId();
        return teamMapper.queryTeamLevel(userId);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public AppBindInvitationCodeRes bindInvitationTest(FaUser faUser) {
        AppUser user = appUserManager.queryByWalletAddres(faUser.getUsername());
        if (user.getInviterId() == null) {
            user.setInviterId(0);
        }
        if (!user.getInviterId().equals(0)) {
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_APP_USER_005);
        }

        AppUser invitationUser = appUserManager.queryInvitationUser(faUser.getEmail());
        if (ObjectUtil.isNull(invitationUser)) {
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_APP_USER_007);
        }
        if (invitationUser.getId().equals(user.getId())) {
            throw new ApiServiceException(LetokenApiResponseEnum.ERROR_APP_USER_008);
        }
        //邀请人不能绑定团队下级邀请码
        AppUserTeamPath invitationUserTeamPath = pathMapper.selectById(invitationUser.getId());
        if (ObjectUtil.isNotNull(invitationUserTeamPath)) {
            if (StringUtils.contains(invitationUserTeamPath.getInvitePath(), user.getId().toString())) {
                throw new ApiServiceException(LetokenApiResponseEnum.ERROR_APP_USER_014);
            }
        }

        LocalDateTime now = LocalDateTime.now();
        //查询被推荐人团队信息
        AppUserTeam appUserTeam = this.getById(user.getId());
        //查询推荐人团队信息 和 团队业绩 并修改
        AppUserTeam invitationTeam = this.getById(invitationUser.getId());
        AppUserTeam invitationTeam2 = new AppUserTeam();
        invitationTeam2.setUserId(invitationTeam.getUserId());
        invitationTeam2.setTeamMember(invitationTeam.getTeamMember() + appUserTeam.getTeamMember() + 1);
        invitationTeam2.setUpdateTime(now);
        if(appUserTeam.getTeamSumValue() > 0 || appUserTeam.getUserAchievement() >0){
            invitationTeam2.setTeamSumValue(invitationTeam.getTeamSumValue()+appUserTeam.getTeamSumValue()+appUserTeam.getUserAchievement());
        }
        this.updateById(invitationTeam2);

        //修改被推荐人上级用户id
        AppUserTeam appUserTeam2 = new AppUserTeam();
        appUserTeam2.setUserId(appUserTeam.getUserId());
        appUserTeam2.setUpdateTime(now);
        appUserTeam2.setInviterId(invitationTeam.getUserId());
        this.updateById(appUserTeam2);

        //修改被推荐人path 先查询推荐人的path
        AppUserTeamPath appUserTeamPath4 = pathMapper.selectById(invitationTeam.getUserId());
        AppUserTeamPath appUserTeamPath5 = new AppUserTeamPath();
        if (appUserTeamPath4.getInvitePath() != null && !"".equals(appUserTeamPath4.getInvitePath())) {
            appUserTeamPath5.setInvitePath(appUserTeamPath4.getUserId() + "," + appUserTeamPath4.getInvitePath());
        } else {
            appUserTeamPath5.setInvitePath(appUserTeamPath4.getUserId().toString());
        }
        appUserTeamPath5.setUserId(appUserTeam.getUserId());
        pathMapper.updateById(appUserTeamPath5);


        //查询推荐人上级 并 修改团队成员人数
        if (invitationTeam.getInviterId() != null && !invitationTeam.getInviterId().equals(0)) {
            AppUserTeamPath appUserTeamPath = pathMapper.selectById(invitationUser.getId());
            String[] path = appUserTeamPath.getInvitePath().split(",");
            //计算团队人数  所有上级的团队人数都要加1
            boolean addInviteTeamMemberFlag = appUserTeamManager.addInviteTeamMember(path, appUserTeam.getTeamMember());
            if (!addInviteTeamMemberFlag) {
                throw new ApiServiceException(LetokenApiResponseEnum.ERROR_APP_USER_015);
//            for (String id : path) {
//                AppUserTeam invitation = this.getById(id);
//                AppUserTeam appUserTeam3 = new AppUserTeam();
//                appUserTeam3.setUserId(Integer.parseInt(id));
//                appUserTeam3.setUpdateTime(now);
//                appUserTeam3.setTeamMember(invitation.getTeamMember() + appUserTeam.getTeamMember() + 1);
//                this.updateById(appUserTeam3);
//            }
            }
        }

        //修改被推荐人 所有团队用户path
//        List<AppUserTeamPath> pathList = pathMapper.getPathList(appUserTeam.getUserId());
//        if (pathList != null && pathList.size() > 0) {
//            for (AppUserTeamPath appUserTeamPath : pathList) {
//                appUserTeamPath.setInvitePath(appUserTeamPath.getInvitePath() + "," + appUserTeamPath5.getInvitePath());
//                pathMapper.updateById(appUserTeamPath);
//            }
//        }
        // 拿到所有自己的下级
        List<Integer> pathIdList = pathMapper.queryTeamPathUserIdByInviteId(appUserTeam.getUserId());
        //修改自己所有下级的path路径，内容是加上我上级的所有上级  因为我的上级也有也可能有很多上级
        if (CollUtil.isNotEmpty(pathIdList)) {
            appUserTeamPathManager.updateTeamPathByInvite(pathIdList, appUserTeamPath5.getInvitePath());
        }

        appUserIssueService.upgrade(user.getId(),null,invitationUser.getId(),1);
        //修改推荐人上级团队业绩
        if(appUserTeam.getTeamSumValue() > 0 || appUserTeam.getUserAchievement() >0){
            appUserIssueService.addTeamValue(invitationUser.getId(),new BigDecimal(appUserTeam.getTeamSumValue()+appUserTeam.getUserAchievement()),1);
        }
        user.setInviterId(invitationUser.getId());
        user.updateById();

        //更新用户缓存
        AppLoginTokenRedis.me().put(WebUtils.getToken(), user);
        AppBindInvitationCodeRes res = new AppBindInvitationCodeRes();
       // res.setInvitationCode(req.getInvitationCode());
        res.setUserName(invitationUser.getUserName());
        res.setUserId(invitationUser.getId());
        return res;
    }

    public void addMallTeamValue(Integer userId, BigDecimal amount) {
        AppUserTeamPath appUserTeamPath = appUserTeamPathMapper.selectById(userId);
        if (appUserTeamPath == null) {
            return;
        }
        if (appUserTeamPath.getInvitePath() == null || appUserTeamPath.getInvitePath() == "" || appUserTeamPath.getInvitePath() == "0") {
            return;
        }
        String[] path = appUserTeamPath.getInvitePath().split(",");
        List<AppUserTeam> teamList = new ArrayList<>();
        for (String inviteID : path) {
            AppUserTeam appUserTea1 = new AppUserTeam();
            AppUserTeam appUserTeam = appUserTeamMapper.selectById(inviteID);
            if (appUserTeam == null) {
                break;
            }
            appUserTea1.setUserId(appUserTeam.getUserId());
            appUserTea1.setTeamMallAchievement(appUserTeam.getTeamMallAchievement().add(amount));
            teamList.add(appUserTea1);
        }
        appUserTeamService.updateBatchById(teamList);

    }

    public void addFundTeamValue(Integer userId, BigDecimal amount) {
        AppUserTeamPath appUserTeamPath = appUserTeamPathMapper.selectById(userId);
        if (appUserTeamPath == null) {
            return;
        }
        if (appUserTeamPath.getInvitePath() == null || appUserTeamPath.getInvitePath() == "" || appUserTeamPath.getInvitePath() == "0") {
            return;
        }
        String[] path = appUserTeamPath.getInvitePath().split(",");
        List<AppUserTeam> teamList = new ArrayList<>();
        for (String inviteID : path) {
            AppUserTeam appUserTea1 = new AppUserTeam();
            AppUserTeam appUserTeam = appUserTeamMapper.selectById(inviteID);
            if (appUserTeam == null) {
                break;
            }
            appUserTea1.setUserId(appUserTeam.getUserId());
            appUserTea1.setTeamfundAchievement(appUserTeam.getTeamfundAchievement().add(amount));
            teamList.add(appUserTea1);
        }
        appUserTeamService.updateBatchById(teamList);

    }




    @Autowired
    StringRedisTemplate redisTemplate;

    @Override
    public QueryConsumerInfoRes consumerInfo() {
        Integer userId = WebUtils.getUserId();
        QueryConsumerInfoRes res = new QueryConsumerInfoRes();
        BigDecimal consumerValue = teamMapper.queryConsumerValue(userId);
        if (ObjectUtil.isEmpty(res)){
            return null;
        }
        res.setConsumerValue(consumerValue);
        // todo 实时值
        res.setWeightedDividends(calculateConsumerValue.weightedDividends(userId));
        res.setThreshold(res.getWeightedDividends().multiply(ConstantsValue.CONSUME_THRESHOLD));

        final String dateKey = APP_CONSUMER_DATE_MARK;
        // 证明已经开始有判定了
        String date ;
        if (redisTemplate.hasKey(dateKey)){
            // 上次判定时间
            date = redisTemplate.opsForValue().get(dateKey);
            res.setCompliance(ConstantsValue.I_0);
            // 判定达标
            if ( !calculateConsumerValue.start() && calculateConsumerValue.hasKey(calculateConsumerValue.getKey(), String.valueOf(userId))){
                res.setCompliance(ConstantsValue.I_1);
            }else if (calculateConsumerValue.isNewUser(userId)){
                res.setCompliance(ConstantsValue.I_F1);
            }
        }else {
            // 上线时间
            date  = calculateConsumerValue.getInitDate();
        }
        res.setNextDate(LocalDate.parse(date,LocalDateTool.yyyyMMdd).plusDays(ConstantsValue.CONSUME_DETERMINE_CYCLE).format(LocalDateTool.yyyyMMdd));

        res.setNextDate("待定");
        return res;

    }


    @Override
    public PageData<ConsumerValueHistoryRes> consumerValueHistory(ConsumerValueHistoryReq req) {
        Integer userId = WebUtils.getUserId();
        if (ObjectUtil.isEmpty(userId)){
            return null;
        }
        req.setUserId(userId);
        Page<ConsumerValueHistoryRes> page = new Page<>(req.getPageReq().getPage(), req.getPageReq().getSize());
        Page<ConsumerValueHistoryRes> res = teamMapper.consumerValueHistoryRes(page, req);
        return PageDataUtil.getPageData(res);
    }



}
